Horizontal curb returns
Description
-
This is a custom interactive tool for creating alignment using points.
-
The user selects a feature definition and name, places data points, and then right-clicks to complete the command which creates a complex horizontal alignment with the given information.
-
The HorizontalAlignmentCreator class which extends DgnElementSetTool which handles different events to interact with UI, the HorizontalAlignmentCreator class overrides the events here in this tool .
Remarks
-
This sample code is a part of ManagedSDKExample which you get with SDK installation under "examples" section in SDK installation directory.
-
If you encounter any error while using DgnElementSetTool class, make sure to add a reference to Bentley.DgnDisplayNet.dll by selecting Project > Add Reference or change the projects .csproj file to add reference to this dll .
-
The default dll location will be "C:\Program Files\Bentley\OpenRoads Designer CE 10.11\OpenRoadsDesigner\Bentley.DgnDisplayNet.dll".
Source Code
//Required References
using System.Collections.Generic;
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.Elements;
using Bentley.CifNET.LinearGeometry;
using Bentley.GeometryNET;
using Bentley.MstnPlatformNET;
using Bentley.CifNET.GeometryModel.SDK;
using Bentley.CifNET.GeometryModel.SDK.Edit;
using Bentley.CifNET.SDK.Edit;
using Bentley.CifNET.Formatting;
namespace ManagedSDKExample.Examples
{
class HorizontalCurbReturns : DgnElementSetTool
{
List<DPoint3d> m_points = new List<DPoint3d>();
//setup
internal static DgnModel activeModel = Bentley.MstnPlatformNET.Session.Instance.GetActiveDgnModel();
internal static ModelInfo info = activeModel.GetModelInfo();
double UORS_TO_METER = 1.0 / info.UorPerMeter;
internal static double m_defaultUnitsToMeters = FormatSettingsConstants.GetMasterUnitsToMeters();
double MASTER_TO_METER = 1.0 * m_defaultUnitsToMeters;
/*----------------------------------------------------------------------------------------------**/
/* Write Function | The user is prompted to place 4 data points, representing 2 lines that cross.
* The lines are offset by a specified radius to create the center of an arc.
* The program creates an arc from the given radius and returns the beginning of
* the first line, the arc, and then the end of the second line.
/*--------------+---------------+---------------+---------------+---------------+----------------*/
internal void CreateLinesFromPoints()
{
//converting the point coordinates to meters
DPoint3d firstTangentStartPoint = m_points[0];
firstTangentStartPoint.X *= UORS_TO_METER;
firstTangentStartPoint.Y *= UORS_TO_METER;
firstTangentStartPoint.Z *= UORS_TO_METER;
DPoint3d firstTangentEndPoint = m_points[1];
firstTangentEndPoint.X *= UORS_TO_METER;
firstTangentEndPoint.Y *= UORS_TO_METER;
firstTangentEndPoint.Z *= UORS_TO_METER;
DPoint3d lastTangentStartPoint = m_points[2];
lastTangentStartPoint.X *= UORS_TO_METER;
lastTangentStartPoint.Y *= UORS_TO_METER;
lastTangentStartPoint.Z *= UORS_TO_METER;
DPoint3d lastTangentEndPoint = m_points[3];
lastTangentEndPoint.X *= UORS_TO_METER;
lastTangentEndPoint.Y *= UORS_TO_METER;
lastTangentEndPoint.Z *= UORS_TO_METER;
double radius = 200 * MASTER_TO_METER;
//uses the input points and radius to get a list of elements consisting of a starting tangent line, arc, and ending tangent line
List<LinearElement> linElems = GetArcBetweenTwoElements(firstTangentStartPoint, firstTangentEndPoint, lastTangentStartPoint, lastTangentEndPoint, radius);
if (linElems.Count > 0)
{
ConsensusConnectionEdit con = ConsensusConnectionEdit.GetActive();
GeometricModel gm = con.GetOrCreateGeometricModel();
if (gm == null)
{
con.Close();
con.Dispose();
return;
}
//adds elements to alignment to display
LinearComplex complexAlign = LinearComplex.Create1(linElems.ToArray(), false, false, 0.001);
con.StartTransientMode();
Bentley.CifNET.GeometryModel.SDK.Alignment al = gm.CreateAlignmentByLinearElement(complexAlign, true);
con.PersistTransients();
}
else
System.Windows.Forms.MessageBox.Show("One or both of the tangents are too short for the given radius. Try again.");
}
/*------------------------------------------------------------------------------------**/
/* Creation
/*--------------+---------------+---------------+---------------+---------------+------*/
//Caller must check that the number of elements in the returned list is greater than 0
//Expected input data format: meters
public static List<LinearElement> GetArcBetweenTwoElements(Bentley.GeometryNET.DPoint3d firstTangentStartPoint, Bentley.GeometryNET.DPoint3d firstTangentEndPoint,
Bentley.GeometryNET.DPoint3d lastTangentStartPoint, Bentley.GeometryNET.DPoint3d lastTangentEndPoint, double arcRadius)
{
//setup
List<LinearElement> linElems = new List<LinearElement>();
//creating the first tangent line
Line firstTangentLine = Line.Create1(firstTangentStartPoint, firstTangentEndPoint);
//creating the last tangent line
Line lastTangentLine = Line.Create1(lastTangentStartPoint, lastTangentEndPoint);
//getting the angle between lines
double angleBetweenLines = firstTangentLine.Direction - lastTangentLine.Direction;
if (angleBetweenLines < 0) angleBetweenLines += 2 * System.Math.PI;
Hand hand;
Line firstTangentOffset, lastTangentOffset;
//If the angle created by the lines is less than 180 degrees, creates a clockwise arc using offset lines in the positive direction to find the center point
if (angleBetweenLines < System.Math.PI)
{
hand = Hand.Clockwise;
firstTangentOffset = Line.Create1(firstTangentLine.GetPointAtDistanceOffset(0.0, arcRadius).Coordinates, firstTangentLine.GetPointAtDistanceOffset(firstTangentLine.Length, arcRadius).Coordinates);
lastTangentOffset = Line.Create1(lastTangentLine.GetPointAtDistanceOffset(0.0, arcRadius).Coordinates, lastTangentLine.GetPointAtDistanceOffset(lastTangentLine.Length, arcRadius).Coordinates);
}
//If the angle created by the lines is greater than 180 degrees, creates a counterclockwise arc using offset lines in the negative direction to find the center point
else
{
hand = Hand.CounterClockwise;
firstTangentOffset = Line.Create1(firstTangentLine.GetPointAtDistanceOffset(0.0, -arcRadius).Coordinates, firstTangentLine.GetPointAtDistanceOffset(firstTangentLine.Length, -arcRadius).Coordinates);
lastTangentOffset = Line.Create1(lastTangentLine.GetPointAtDistanceOffset(0.0, -arcRadius).Coordinates, lastTangentLine.GetPointAtDistanceOffset(lastTangentLine.Length, -arcRadius).Coordinates);
}
//getting the intersection of the offset lines
LinearIntersectionCollection intersectionCollection = firstTangentOffset.Intersect(lastTangentOffset);
if (intersectionCollection.Count > 0)
{
//the intersection of the offset lines is the center point of the arc
Bentley.GeometryNET.DPoint3d centerPoint = intersectionCollection.Item(0).PointOn1.Coordinates;
//getting lines perpendicular from the center point to the tangent lines to find the start and end points of the arc
LinearPoint startPointLinear = firstTangentLine.ProjectPointOnPerpendicular(centerPoint);
Bentley.GeometryNET.DPoint3d arcStartPoint = startPointLinear.Coordinates;
Line startDirectionLine = Line.Create1(centerPoint, arcStartPoint);
LinearPoint endPointLinear = lastTangentLine.ProjectPointOnPerpendicular(centerPoint);
Bentley.GeometryNET.DPoint3d arcEndPoint = endPointLinear.Coordinates;
Line endDirectionLine = Line.Create1(centerPoint, arcEndPoint);
//creating the starting tangent to the arc
Line startingTangent = Line.Create1(firstTangentStartPoint, arcStartPoint);
linElems.Add(startingTangent);
//creating the arc
Bentley.CifNET.LinearGeometry.CircularArc arc = Bentley.CifNET.LinearGeometry.CircularArc.Create8(centerPoint, arcRadius, startDirectionLine.Direction, endDirectionLine.Direction, hand);
linElems.Add(arc);
//creating the ending tangent to the arc
Line endLine = Line.Create1(arcEndPoint, lastTangentEndPoint);
linElems.Add(endLine);
}
return linElems;
}
protected override void OnPostInstall()
{
NotificationManager.OutputPrompt("Select first data point.");
BeginDynamics();
}
//adds points on click
protected override bool OnDataButton(DgnButtonEvent ev)
{
if (m_points.Count == 0)
{
BeginDynamics();
}
m_points.Add(ev.Point);
if (m_points.Count == 4)
{
CreateLinesFromPoints();
EndDynamics();
m_points.Clear();
NotificationManager.OutputPrompt("Command complete. Select first data point or pick element selection tool to exit command.");
}
else
{
NotificationManager.OutputPrompt("Select next data point or right click to cancel the command.");
}
return true;
}
//terminates command (right click)
protected override bool OnResetButton(DgnButtonEvent ev)
{
EndDynamics();
m_points.Clear();
NotificationManager.OutputPrompt("Command terminated. Select first data point or pick element selection tool to exit command.");
return false;
}
//allows preview lines to be drawn
protected override void OnDynamicFrame(DgnButtonEvent ev)
{
RedrawElems redraw = new RedrawElems();
redraw.DrawMode = DgnDrawMode.TempDraw;
redraw.DrawPurpose = DrawPurpose.Dynamics;
redraw.SetViewport(ev.Viewport);
if (m_points.Count > 1)
{
LineStringElement lse = new LineStringElement(Session.Instance.GetActiveDgnModel(), null, m_points.GetRange(0, 2).ToArray());
redraw.DoRedraw(lse);
if (m_points.Count > 3)
{
LineStringElement lse2 = new LineStringElement(Session.Instance.GetActiveDgnModel(), null, m_points.GetRange(2, 2).ToArray());
redraw.DoRedraw(lse2);
}
}
}
protected override void OnRestartTool()
{
InstallNewInstance();
}
public override StatusInt OnElementModify(Element element)
{
return StatusInt.Error;
}
public static void InstallNewInstance()
{
HorizontalCurbReturns tool = new HorizontalCurbReturns();
tool.InstallTool();
}
}
}